<?php
/**
* 微信接口
* 文档：http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97
* @author mc
* @version 2016年11月3日
*/
class weixin{
    private static $TOKEN      = "istravelink";
    private static $ourWxId    = "";//我们的微信ID
    private static $userOpenId = "";//用户的OPENID
    private static $EventKey   = "";//用户的OPENID
    private static $appId = "";//用户的OPENID
    private static $secret= "";//用户的OPENID
    private static $tokenType_main = 'main_token';
    private static $tokenType_js = 'js_token';
    private static $tokenType_ticket = 'js_ticket';
    
    
    //初始化
    public  static  function  initParam($paramArr  = array()){
    	$options = array(
    			'appId'        => '',    #服务号的 appId
    			'appSecret'    => '',    #服务号的 appSecret
    	);
    	if (is_array($paramArr))$options = array_merge($options, $paramArr);
    	extract($options);
    
    	self::$appId  = $appId;
    	self::$secret = $appSecret;
    
    	return  true;
    }
    
    /**
     * 签名的验证
     */
	private static function checkSignature($paramArr) {
		$options = array(
			'signature'    => '', #微信加密签名
			'timestamp'    => '', #时间戳
			'nonce'        => '', #随机数
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
		$token = self::$TOKEN;
		$tmpArr = array($token, $timestamp, $nonce);
		sort($tmpArr);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );

		if( $tmpStr == $signature ){
			return true;
		}else{
			return false;
		}
	}

    /**
     * 申请消息接口的验证
     * 网址接入 公众平台用户提交信息后，微信服务器将发送GET请求到 这个参数
     */
	public static function verification($paramArr) {
		$options = array(
			'token'        => '', #TOKEN
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options); 
        if(!empty($token)){
            self::$TOKEN = $token;
        }
        $signature = $_GET("signature");
        $timestamp = $_GET("timestamp");
        $nonce     = $_GET("nonce");
        $echoStr   = $_GET("echostr");
        
        //进行验证
        if(self::checkSignature(array(
			'signature'    => $signature,
			'timestamp'    => $timestamp,
			'nonce'        => $nonce,
		))){
            echo $echoStr;
        }
    }


    /**
     * 接受用户发送的消息
     */
    public static function receiveMsg($paramArr) {
		$options = array(
			'subscribeCallback'        => false, #订阅回调函数
			'unsubscribeCallback'      => false, #取消订阅回调函数
			'clickCallback'            => false, #自定义菜单点击事件调函数
			'locationCallback'         => false, #上报地理位置事件回调函数
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if(!$postStr)return array();
        
        $outArr = array();
        $postObj           = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
		
        self::$userOpenId  = $postObj->FromUserName ? (string)$postObj->FromUserName : "";
        self::$ourWxId     = $postObj->ToUserName ? (string)$postObj->ToUserName : "";
        $msgType           = (string)$postObj->MsgType;
        $outArr = (array)$postObj;
        $outArr["OurWeixinId"] = (string)self::$ourWxId;
        $outArr["UserOpenId"]  = (string)self::$userOpenId;   
        if('event' == $msgType){#事件的处理            
            switch((string)$postObj->Event){
            	case "location_select": #地址事件
            		if($locationCallback){
            			$sendInfo = (array)($postObj->SendLocationInfo);
            			$outArr['Location_X'] = (double)$sendInfo['Location_X'];
            			$outArr['Location_Y'] = (double)$sendInfo['Location_Y'];
            			call_user_func($locationCallback, $outArr);
            		}
            		break;
                case "subscribe": #订阅事件
                    if($subscribeCallback){
                        call_user_func($subscribeCallback, $outArr);
                    }
                    break;
                case "unsubscribe": #取消订阅
                    if($unsubscribeCallback){
                        call_user_func($unsubscribeCallback, $outArr);
                    }
                    break;
                case "CLICK": #自定义菜单点击事件
                    self::$EventKey    = $postObj->EventKey ? (string)$postObj->EventKey : "";
                    $outArr["MenuKey"]  = (string)self::$EventKey;
                    if($clickCallback){
                        call_user_func($clickCallback, $outArr);
                    }
                    break;
            }
        }else{#普通消息
            if("text"== $msgType){                
                $outArr["Content"] = (string)$postObj->Content;
            }elseif("image"== $msgType){
                $outArr["PicUrl"]     = (string)$postObj->PicUrl;
                #地址消息
            }elseif("location"== $msgType){
            	if($locationCallback){
            		call_user_func($locationCallback, $outArr);
            	}
            }
            return $outArr;
        }

        
    }

    /**
     * 获得回复消息的通用部分
     */
    private static function getAnswerBaseXml($type){
        return "<xml>
                <ToUserName><![CDATA[". self::$userOpenId ."]]></ToUserName>
                <FromUserName><![CDATA[". self::$ourWxId ."]]></FromUserName>
                <CreateTime>".SYSTEM_TIME."</CreateTime>
                ";
    }

    /**
     * 回复文本消息
     */
    public static function answerText($paramArr) {
		$options = array(
			'content'        => '', #内容
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);

        if(!$content)return '';
        
        $xmlStr  = self::getAnswerBaseXml();
        $content = trim($content);
        
        return $xmlStr . "<MsgType><![CDATA[text]]></MsgType>
               <Content><![CDATA[{$content}]]></Content>
               </xml>";        
    }

     /**
     * 回复音乐消息
     */
    public static function answerMusic($paramArr) {
		$options = array(
			'title'           => '', #标题
			'desc'            => '', #描述
			'musicUrl'        => '', #音乐链接
			'hQMusicUrl'      => '', #高质量音乐链接，WIFI环境优先使用该链接播放音乐
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);


        $xmlStr  = self::getAnswerBaseXml();
		$title = trim($title);
		if($desc){
			$desc = trim($desc);
		}
        return $xmlStr . "<MsgType><![CDATA[music]]></MsgType>
                         <Music>
                         <Title><![CDATA[{$title}]]></Title>
                         <Description><![CDATA[{$desc}]]></Description>
                         <MusicUrl><![CDATA[{$musicUrl}]]></MusicUrl>
                         <HQMusicUrl><![CDATA[{$hQMusicUrl}]]></HQMusicUrl>
                         </Music>
                         </xml>";
    }

    /**
     * 回复列表
     */
    public static function answerList($paramArr) {
		$options = array(
			'dataArr'        => array(), #列表内容 array('Title'=>''，'Description'=>''，'PicUrl'=>''，'Url'=>'');
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);

        if(!$dataArr)return '';

        $xmlStr  = self::getAnswerBaseXml();
        $xmlStr .= "<MsgType><![CDATA[news]]></MsgType>
                    <ArticleCount>".count($dataArr)."</ArticleCount>
                    <Articles>";
        foreach($dataArr as $d){
        	
			$title = trim($d['Title']);
			if(isset($d['Description']) && $d['Description']){
				$desc = trim($d['Description']);
			}
            $textTpl = "
                         <item>
                         <Title><![CDATA[%s]]></Title>
                         <Description><![CDATA[%s]]></Description>
                         <PicUrl><![CDATA[%s]]></PicUrl>
                         <Url><![CDATA[%s]]></Url>
                         </item>";

            $xmlStr .= sprintf($textTpl,$title, $desc, $d['PicUrl'], $d['Url']);
        }
        $xmlStr .= "
                    </Articles>
                    </xml>";
        
        return $xmlStr;
    }
    /**
     * 根据OPENID获得travelink的用户ID
     */
    public static function getTravelUserByOpenId($paramArr) {
		$options = array( 
			'appId'         => '', #公众账号 ID 如 travelink,
			'openId'        => '', #OPEN ID
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        //$db = API_Db_User::instance();连接数据库
        //return $db->getOne("select traveluserid from t_weixin_user_map where appid = '{$appId}' and openid = '{$openId}'");
    }
    
    
    /**
     * 设置travelink用户id和微信OPENID的映射
     */
    public static function setTravelUserOpenIdMap($paramArr) {
		$options = array( 
			'appId'         => '', #公众账号 ID 
			'openId'        => '', #OPEN ID
			'userId'        => '', #travelink用户ID
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        //$db = API_Db_User::instance();
        //$db->query("insert into t_weixin_user_map(appid,openid,traveluserid,tm) 
                    //values( '{$appId}','{$openId}','{$userId}',".SYSTEM_TIME.")");
        return true;
    }
    
    /**
     * 获得 access_token  
     * 
     */
    
    public static function getAccessToken($paramArr){
        
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'exp'          => 0
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        if(empty($appId)  || empty($appSecret)){
            return  false;
        }
        //先检查 有没有缓存  正常 微信access_token 有效期为 7200秒
		$accessToken = cache_token::get(array(
           'appid'  =>self::$appId,
		   'type'	=>self::$tokenType_main			
		));
		if(!empty($accessToken['token'])){
			return array('state'=>1,'data'=>$accessToken['token']);
		}
        $jsonStr   =   "";
        $jsonStr   =   self::curlPage(array(
                'url'   =>"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}"
        ));
        $jsonArr        = array();
        if($jsonStr){
              $jsonArr  = json_decode($jsonStr,true);
        }
        if(!empty($jsonArr['access_token'])){
        	cache_token::updateToken(array(
	        	'appId'  =>self::$appId,
	        	'type'	=>self::$tokenType_main,
	        	'token' =>$jsonArr['access_token'],
	        	'exTime'=>(int)$jsonArr['expires_in']-100
        	));
            return array('state'=>1,'data'=>$jsonArr['access_token']);
        }else{
            return array('state'=>0,'data'=>$jsonArr['errcode']);
        }  
    }
    
    /**
     * 发送客服消息
     */
    
    public  static  function  sendMsg($paramArr){
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'data'         => ''
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        if(empty($data)){
            return false;
        }
        #获得access_token
        $dataArr = self::getAccessToken(array(
                'appId'        => $appId,    #服务号的 appId
                'appSecret'    => $appSecret,    #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($dataArr['state'])){
            $accessToken  =  $dataArr['data'];
        }else{
            return false;
        }
        $jsonStr   =   "";
        $jsonStr   =   weixin::curlPost(array(
                            'url'       =>'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$accessToken,
                            'postdata'  => !empty($data) ? json_encode($data,true):''
                       ));
        
        $jsonArr  = json_decode($jsonStr,true);
        if(empty($jsonArr['errcode'])){
                return array('state'=>1,'data'=>$jsonArr['errmsg']);
        }else{
                return array('state'=>0,'data'=>$jsonArr['errmsg']);
        }

        
    }
    /**
     * 根据code获取用户openid等前置信息
     */
    public static function getOpenId($paramArr){
    	$options = array(
    			'appId'        => self::$appId,    #服务号的 appId
    			'appSecret'    => self::$secret,    #服务号的 appSecret
    			'code'       => ''
    	);
    	if (is_array($paramArr))$options = array_merge($options, $paramArr);
    	extract($options);
    	
    	if(empty($code)){
    		return false;
    	}
    	$jsonStr   =   "";
    	$jsonStr   =   self::curlPost(array(
    			'url'   =>"https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appId}&secret={$appSecret}&code={$code}&grant_type=authorization_code "
    	));
    	$jsonArr        = array();
    	if($jsonStr){
    		$jsonArr  = json_decode($jsonStr,true);
    	}
        return  !empty ($jsonArr) ? $jsonArr : false;
    }
    
    /**
     * 获得用户基本信息
     * 
     */
     public  static  function getUserInfo($paramArr){
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'openId'       => ''
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        if(empty($openId)){
            return false;
        }
        #获得access_token
        $dataArr = self::getAccessToken(array(
                'appId' => $appId,    #服务号的 appId
                'appSecret'  => $appSecret,    #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($dataArr['state'])){
            $accessToken  =  $dataArr['data'];
        }else{
            return false;
        }
        $jsonStr   =   "";
        $jsonStr   = weixin::curlPage(array(
                            'url' =>'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$accessToken.'&openid='.$openId.'&lang=zh_CN'
                       ));
        $jsonArr   = array();     
        $jsonArr = json_decode($jsonStr,true);
        return  !empty ($jsonArr) ? $jsonArr : false;
     }
     
     /**
      * 获得用户组
      * 
      */
      public  static  function  getUserGroup($paramArr){
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'nextOpenId'   => ''
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        if(empty($appId) || empty($appSecret)){
            return false;
        }
        #获得access_token
        $dataArr = self::getAccessToken(array(
                'appId'        => $appId,        #服务号的 appId
                'appSecret'    => $appSecret,    #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($dataArr['state'])){
            $accessToken  =  $dataArr['data'];
        }else{
            return false;
        }                
        $jsonStr   =   "";
        $jsonStr   =   self::curlPost(array(
                            'url'       =>'https://api.weixin.qq.com/cgi-bin/user/get?access_token='.$accessToken.'&next_openid='.$nextOpenId
                       ));
        $jsonArr   = array();     
        $jsonArr   = json_decode($jsonStr,ture);   
        return  !empty ($jsonArr) ? $jsonArr : false;
      }   
      
      /**
       * 创建自定义菜单
       * 
       */
      public  static   function   createManu($paramArr){
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'data'         => ''
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        if(empty($data) || empty($appId)  || empty($appSecret)){
            return false;
        }
        #获得access_token
        $dataArr = self::getAccessToken(array(
                'appId'        => $appId,    #服务号的 appId
                'appSecret'    => $appSecret,    #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($dataArr['data'])){
            $accessToken  =  $dataArr['data'];
        }else{
            return false;
        }
        $jsonStr   =   "";
        $jsonStr   =   self::curlPost(array(
                            'url'       =>'https://api.weixin.qq.com/cgi-bin/menu/create?access_token='.$accessToken."&ensure_ascii=false",
                            'postdata'  => !empty($data) ? ($data):''
                       ));
        $jsonArr  = json_decode($jsonStr,true);
        if(empty($jsonArr['errcode'])){
                return array('state'=>1,'data'=>$jsonArr['errmsg']);
        }else{
                return array('state'=>0,'data'=>$jsonArr['errmsg']);
        }   
      }
      
      /**
       * 获得自定义菜单
       */
      public   static  function  getManu($paramArr){
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        if(empty($appId)){
            return false;
        }
        #获得access_token
        $dataArr = self::getAccessToken(array(
                'appId'        => $appId,    #服务号的 appId
                'appSecret'    => $appSecret,    #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($dataArr['state'])){
            $accessToken  =  $dataArr['data'];
        }else{
            return false;
        }
         
        $jsonStr   =   "";
        $jsonStr   =   self::curlPost(array(
                            'url'  =>'https://api.weixin.qq.com/cgi-bin/menu/get?access_token='.$accessToken
                       ));
        $jsonArr   = array();     
        $jsonArr   = json_decode($jsonStr,true);   
        return  !empty ($jsonArr) ? $jsonArr : false; 
      }
      /**
       * 获取永久素材列表
       */
      public static function getLibs($paramArr){
      	$options = array(
      			'appId'        => self::$appId,    #服务号的 appId
      			'appSecret'    => self::$secret,    #服务号的 appSecret
      			'data'         => ''
      	);
      	if (is_array($paramArr))$options = array_merge($options, $paramArr);
      	extract($options);
      	if(empty($data) || empty($appId)  || empty($appSecret)){
      		return false;
      	}
      	#获得access_token
      	$dataArr = self::getAccessToken(array(
      	'appId'        => $appId,    #服务号的 appId
      	'appSecret'    => $appSecret,    #服务号的 appSecret
      	));
      	#获得 access_token
      	$accessToken  = "";
      	if(!empty($dataArr['data'])){
      		$accessToken  =  $dataArr['data'];
      	}else{
      		return false;
      	}
      	$jsonStr   =   "";
      	$jsonStr   =   self::curlPost(array(
      			'url'       =>'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token='.$accessToken,
      			'postdata'  => !empty($data) ? ($data):''
      	));
      	return $jsonStr;
      }
      /**
       * 获取素材总数
       */
      public static function get_materialcount($paramArr){
      	$options = array(
      			'appId'        => self::$appId,    #服务号的 appId
      			'appSecret'    => self::$secret,    #服务号的 appSecret
      	);
      	if (is_array($paramArr))$options = array_merge($options, $paramArr);
      	extract($options);
      	if(empty($appId)  || empty($appSecret)){
      		return false;
      	}
      	#获得access_token
      	$dataArr = self::getAccessToken(array(
	      	'appId'        => $appId,    #服务号的 appId
	      	'appSecret'    => $appSecret,    #服务号的 appSecret
      	));
      	#获得 access_token
      	$accessToken  = "";
      	if(!empty($dataArr['data'])){
      		$accessToken  =  $dataArr['data'];
      	}else{
      		return false;
      	}
      	$jsonStr   =   "";
      	$jsonStr   =   self::curlPost(array(
      			'url'       =>'https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token='.$accessToken,
      			'postdata'  => !empty($data) ? ($data):''
      	));
      	$jsonArr  = json_decode($jsonStr,true);
      	if(empty($jsonArr['errcode'])){
      		return array('state'=>1,'data'=>$jsonArr['errmsg']);
      	}else{
      		return array('state'=>0,'data'=>$jsonArr['errmsg']);
      	}
      }
      /**
       * 生成二维码
       */
      
      public  static  function  createQR($paramArr){
        $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'isForever'    =>1,      #是否是永久的
            'sceneId'      =>''      #是否
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        if(empty($appId) || empty($appSecret) || empty ($sceneId)){
            return false;
        }
        #获得access_token
        $dataArr = self::getAccessToken(array(
                'appId'        => $appId,    #服务号的 appId
                'appSecret'    => $appSecret,    #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($dataArr['state'])){
            $accessToken  =  $dataArr['data'];
        }else{
            return false;
        }
        $data      =   array();
        
        $data['action_name']    =  !empty($isForever) ? 'QR_LIMIT_SCENE':'QR_LIMIT_SCENE';
        $data['action_info']    =  array('scene'=>array('scene_id'=>$sceneId)); 
        
        $jsonStr   =   "";
        $jsonStr   =   self::curlPost(array(
                            'url'       =>'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='.$accessToken,
                            'postdata'  => !empty($data) ? json_encode($data,true):''
                       ));
        $jsonArr   = array();     
        $jsonArr   = json_decode($jsonStr,true);   
        return  !empty ($jsonArr) ? $jsonArr : false; 
          
          
      }
      
      /**
       * 发送模板信息接口
       * @param type $paramArr
       * @return type 
       */
      public static function sendTemplateMessage($paramArr){
          $options = array(
            'appId'        => self::$appId,    #服务号的 appId
            'appSecret'    => self::$secret,    #服务号的 appSecret
            'dataArr'           => '', #根据模板定义的参数发送的信息，具体的需要参考微信模板消息参数说明，说明在微信公众号后台
		);
		if (is_array($paramArr))$options = array_merge($options, $paramArr);
		extract($options);
        
        if(empty($appId) || empty($appSecret)  || empty($dataArr)){
            return false;
        }
        
        #获得access_token
        $tokenDataArr = self::getAccessToken(array(
                'appId'        => $appId,       #服务号的 appId
                'appSecret'    => $appSecret,   #服务号的 appSecret
        ));
        #获得 access_token
        $accessToken  = "";
        if(!empty($tokenDataArr['state'])){
            $accessToken  =  $tokenDataArr['data'];
        }else{
            return false;
        }
        
        
        $jsonStr   =   "";
        $jsonStr   =   self::curlPost(array(
                            'url'       =>'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$accessToken,
                            'postdata'  => !empty($dataArr) ? json_encode($dataArr):''
                       ));
        $jsonArr   = array();     
        $jsonArr   = json_decode($jsonStr,true); 
        
        if(!empty($jsonArr['errmsg'])) {
            if($jsonArr['errmsg']=='ok' && $jsonArr['errcode']=='0') {
                return true;
            }
        }else {
            return false;
        }
      }
      
      /**
       *  利用curl的形式获得页面请求 用这个函数取代file_get_contents
       */
      public static function curlPage($paramArr){
      	if (is_array($paramArr)) {
      		$options = array(
      				'url'      => false, #要请求的URL数组
      				'timeout'  => 2,#超时时间 s
      		);
      		$options = array_merge($options, $paramArr);
      		extract($options);
      	}
      	$timeout = (int)$timeout;
      
      	if(0 == $timeout || empty($url))return false;
      
      	$ch = curl_init();
      	curl_setopt($ch, CURLOPT_URL, $url);
      	curl_setopt($ch, CURLOPT_HEADER, 0);
      	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
      	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//跳过ssl认证
      	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
      	if(defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')){
      		curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); #避免首先解析ipv6
      	}
      	$data = curl_exec($ch);
      	curl_close($ch);
      	return $data;
      }
      /**
       *  利用curl POST数据:https请求需要ssl证书
       */
      public static function curlPost($paramArr){
      	 
      	$options = array(
      			'url'      => false, //要请求的URL数组
      			'postdata' => '', //POST的数据
      			'timeout'  =>5,//超时时间 s
      	);
      	if (is_array($paramArr))$options = array_merge($options, $paramArr);
      	extract($options);
      	$timeout = (int)$timeout;
      	if(0 == $timeout || empty($url))return false;
      	$ch = curl_init();
      	curl_setopt ($ch, CURLOPT_URL, $url);
      	curl_setopt ($ch, CURLOPT_POSTFIELDS, $postdata);
      	curl_setopt ($ch, CURLOPT_POST, true);
      	curl_setopt ($ch, CURLOPT_AUTOREFERER, true);
      	curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
      	curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
      	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
      	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//跳过ssl认证
      	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
      	if(defined('CURLOPT_IPRESOLVE') && defined('CURL_IPRESOLVE_V4')){//避免首先解析ipv6
      		curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); 
      	}
      	$content = curl_exec( $ch );
      	curl_close ( $ch );
      	return $content;
      }
      
      
      /**
       * jssdk相关
       */
      //获取jssdk签名
      public static function getSignPackage() {
      	$jsapiTicket = self::getJsApiTicket();
      
      	// 注意 URL 一定要动态获取，不能 hardcode.
      	$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
      	$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
      	$timestamp = time();
      	$nonceStr = self::createNonceStr();
      
      	// 这里参数的顺序要按照 key 值 ASCII 码升序排序
      	$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
      
      	$signature = sha1($string);
      
      	$signPackage = array(
      			"appId"     => self::$appId,
      			"nonceStr"  => $nonceStr,
      			"timestamp" => $timestamp,
      			"url"       => $url,
      			"signature" => $signature,
      			"rawString" => $string
      	);
      	return $signPackage;
      }
      //获取临时票据
      public static function getJsApiTicket() {
      	// jsapi_ticket 应该全局存储与更新，写入缓存
      	$jsapi_ticket  = cache_token::get(array(
      		'appId'=>self::$appId,
      		'type'=>self::$tokenType_ticket
      	));
      	if(!$jsapi_ticket) {
      		$jsToken = self::getJsToken();
      		$jsonStr = "";
      		$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$jsToken";
      		$jsonStr   =   self::curlPage(array(
      				'url'=>$url
      		));
      		$jsonArr        = array();
      		if($jsonStr){
      			$jsonArr  = json_decode($jsonStr,true);
      		}
      		if(!empty($jsonArr['ticket'])){
      			cache_token::updateToken(array(
      			'appId'  =>self::$appId,
      			'type'	=>self::$tokenType_ticket,
      			'token' =>$jsonArr['ticket'],
      			'exTime'=>(int)$jsonArr['expires_in']-100
      			));
      			return $jsonArr['ticket'];
      		}
      	}
      	 
      	return $jsapi_ticket;
      }
      public static function getJsToken() {
      	// access_token 应该全局存储与更新，以下代码以写入到文件中做示例
      	$jsToken = cache_token::get(array(
      		'appId'=>self::$appId,
      		'type'=>self::$tokenType_js
      	));
      	if (!$jsToken) {
      		$jsonStr = '';
      		$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".self::$appId."&secret=".self::$secret;
      		$jsonStr   =   self::curlPage(array(
      			'url'=>$url
      		));
      		$jsonArr        = array();
      		if($jsonStr){
      			$jsonArr  = json_decode($jsonStr,true);
      		}
      		if(!empty($jsonArr['access_token'])){
      			cache_token::updateToken(array(
	      			'appId'  =>self::$appId,
	      			'type'	=>self::$tokenType_js,
	      			'token' =>$jsonArr['access_token'],
	      			'exTime'=>(int)$jsonArr['expires_in']-100
      			));
      			return $jsonArr['access_token'];
      		}
      	} 
      	return $jsToken;
      }
      public static function createNonceStr($length = 16) {
      	$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
      	$str = "";
      	for ($i = 0; $i < $length; $i++) {
      		$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
      	}
      	return $str;
      }
      
}
?>